home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / flying-6.11 / wall.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-30  |  5.9 KB  |  257 lines

  1. #ifndef _global_h
  2. #    include "global.h"
  3. #endif
  4.  
  5. #ifndef _wall_h
  6. #    include "wall.h"
  7. #endif
  8. #ifndef _ball_h
  9. #    include "ball.h"
  10. #endif
  11. #ifndef _game_h
  12. #    include "game.h"
  13. #endif
  14.  
  15. //
  16. // -------------------------------------------------------------------------
  17. //   class Wall:  Begrenzungs-Objekt
  18. // -------------------------------------------------------------------------
  19. //
  20.  
  21. Wall::Wall( double x1, double y1, double x2, double y2 )
  22. : p1(x1,y1), p2(x2,y2)
  23. {
  24.     d  = p2-p1;                   // Richtungsvektor der Wand
  25.     ds = d.TurnLeft().Norm1();    // normierter senkrechter Vektor zur Richtung
  26. }
  27. Wall::Wall( const Vec2 &v1, const Vec2 &v2 )
  28. : p1(v1), p2(v2)
  29. {
  30.     d  = p2-p1;                   // Richtungsvektor der Wand
  31.     ds = d.TurnLeft().Norm1();    // normierter senkrechter Vektor zur Richtung
  32. }
  33.  
  34.  
  35. Wall::~Wall() { }
  36.  
  37. void Wall::Info() {
  38.     printf( "%02d: Wall:       %08lx: (%4.1f,%4.1f) - (%4.1f,%4.1f)\n",
  39.                 Object::id, (unsigned long)this,
  40.                 (double)p1.X(), (double)p1.Y(),
  41.                 (double)p2.X(), (double)p2.Y() );
  42. }
  43.  
  44. Real Wall::HitFromBall( Ball *b ) {
  45.     if (b->IsIdle())        return MAX_TIME;
  46.  
  47. #if (EasyWall)
  48. Real        t1, l1;
  49. Vec2    direct_v;
  50. Vec2    balls_edge;
  51.  
  52.     b->V().Split( ds, &direct_v );
  53.     if (direct_v.X()==0.0&&direct_v.Y()==0.0)    return NO_HIT;
  54.     balls_edge = b->P() + direct_v.Norm1()*b->R();
  55.  
  56.     if (Vec2::Solve( p1, d, balls_edge, direct_v, &t1 ))    return NO_HIT;
  57. #if (ABORT_CALC_WALL)
  58.     if    ( t1>b->collision_time-current_time+EPS )                return NOT_REACHABLE;
  59. #endif
  60.  
  61.     if (t1<-EPS)                    return NO_HIT;
  62.     if (d.X()!=0.0) {
  63.         l1 = ( balls_edge.X() + t1*b->VX() - p1.X() ) / d.X();
  64.     }
  65.     else if (d.Y()!=0.0) {
  66.         l1 = ( balls_edge.Y() + t1*b->VY() - p1.Y() ) / d.Y();
  67.     }
  68.     else                                 return NO_HIT;    // Wand ohne LΣnge ??
  69.     if ( l1>=0.0 && l1<=1.0 )    return t1;
  70.     return NO_HIT;
  71.  
  72. #else
  73. Real    A,B,C;    // Hilfsvariablen
  74. Real    l1, t1;    // erste L÷sung des Gleichungssystems
  75. Real    l2, t2;    // zweite L÷sung des Gleichungssystems
  76.  
  77. //
  78. // erste Variante des Gleichungssystems, nur l÷sbar wenn VX() ungleich 0
  79. //
  80.     if ( d.X() != 0.0 ) {
  81.  
  82.         A = b->VY() - ( b->VX()/d.X()*d.Y() );
  83.         if ( A!=0.0 )    {
  84.  
  85.             B = p1.Y()-b->PY() + ( b->PX()-p1.X() )/d.X()*d.Y();
  86.             C = b->R() * (ds.Y() - (ds.X()/d.X()*d.Y()));
  87.     //
  88.     // eine Kollision findet statt, wenn beide Zeiten gr÷▀er/gleich 0
  89.     //
  90.             t1 = (B+C)/A;
  91.             if ( t1<-EPS )        return NO_HIT;
  92.             t2 = (B-C)/A;
  93.             if ( t2<-EPS )        return NO_HIT;
  94.     //
  95.     // fⁿr die kleinere Zeit mu▀ l? zwischen 0 und 1 liegen
  96.     //
  97.             if ( t1<t2 ) {
  98. #if (ABORT_CALC_WALL)
  99.                 if    ( t1>b->collision_time-current_time+EPS ) {
  100.                     DBG2(AbortCalc,"    WallHit from %d to %d aborted.\n",b->Object::id,id);
  101.                     return NOT_REACHABLE;
  102.                 }
  103. #endif
  104.                 l1 = ( b->PX() + t1*b->VX() - p1.X() - b->R()*ds.X() ) / d.X();
  105.                 if ( l1>=0.0 && l1<=1.0 )    return t1;
  106.                 else                                return NO_HIT;
  107.             }
  108.             else {
  109. #if (ABORT_CALC_WALL)
  110.                 if    ( t2>b->collision_time-current_time+EPS ) {
  111.                     DBG2(AbortCalc,"    WallHit from %d to %d aborted.\n",b->Object::id,id);
  112.                     return NOT_REACHABLE;
  113.                 }
  114. #endif
  115.                 l2 = ( b->PX() + t2*b->VX() - p1.X() + b->R()*ds.X() ) / d.X();
  116.                 if ( l2>=0.0 && l2<=1.0 )    return t2;
  117.                 else                                return NO_HIT;
  118.             }
  119.         }
  120.     }
  121.  
  122. //
  123. // Zweite Variante des Gleichungssystems, nur l÷sbar, wenn VY() ungleich 0.
  124. //
  125.     if ( d.Y() != 0.0 ) {
  126.  
  127.         A = b->VX() - ( b->VY()/d.Y()*d.X() );
  128.         if ( A!=0.0 )    {
  129.  
  130.             B = p1.X()-b->PX() + ( b->PY()-p1.Y() )/d.Y()*d.X();
  131.             C = b->R() * (ds.X() - (ds.Y()/d.Y()*d.X()));
  132.     //
  133.     // eine Kollision findet statt, wenn beide Zeiten gr÷▀er/gleich 0
  134.     //
  135.             t1 = (B+C)/A;
  136.             if ( t1<-EPS )        return NO_HIT;
  137.             t2 = (B-C)/A;
  138.             if ( t2<-EPS )        return NO_HIT;
  139.     //
  140.     // fⁿr die kleinere Zeit mu▀ l? zwischen 0 und 1 liegen.    //
  141.             if ( t1<t2 ) {
  142.                 l1 = ( b->PY() + t1*b->VY() - p1.Y() - b->R()*ds.Y() ) / d.Y();
  143.                 if ( l1>=0.0 && l1<=1.0 )    return t1;
  144.                 else                                return NO_HIT;
  145.             }
  146.             else {
  147.                 l2 = ( b->PY() + t2*b->VY() - p1.Y() + b->R()*ds.Y() ) / d.Y();
  148.                 if ( l2>=0.0 && l2<=1.0 )    return t2;
  149.                 else                                return NO_HIT;
  150.             }
  151.         }
  152.     }
  153.  
  154. //
  155. // keine L÷sung m÷glich ?
  156. //
  157.     return NO_HIT;
  158. #endif
  159. }
  160.  
  161.  
  162. void Wall::CollideWithBall( Ball *b ) {
  163. Vec2    o, p;
  164.  
  165.     g->HitWall(b);
  166.     b->V().Split(ds,&o,&p);
  167.     b->SetV(p-o);
  168. }
  169.  
  170. //
  171. // -------------------------------------------------------------------------
  172. //   class XWall:  Wand ohne Begrenzung
  173. // -------------------------------------------------------------------------
  174. //
  175.  
  176. XWall::~XWall()    { }
  177.  
  178. Real XWall::HitFromBall( Ball *b )
  179. {
  180.     if (b->IsIdle())        return MAX_TIME;
  181.  
  182. Real    min_time;                    // ausgerechnete Zeit
  183. Real    sx=p1.X()-b->PX();        // zurⁿckzulegende Strecke (ohne Radius)
  184.  
  185.     if (( sx > 0.0 ) && ( b->VX() > 0.0 )) {
  186.         sx -= b->R();                // Kugelradius berⁿcksichtigen
  187.     }
  188.     else if ( sx < 0.0 ) {
  189.         if ( b->VX() >= 0.0 )        return NO_HIT;
  190.         sx += b->R();                // Kugelradius berⁿcksichtigen
  191.     }
  192.     else if (b->VX()==0.0)            return NO_HIT;
  193.  
  194.     min_time = sx / b->VX();
  195.  
  196. #ifdef DEBUG
  197.     if (debug&XWallHit) {
  198.         printf( "XWall-Hit in %g secs\n", (double)min_time );
  199.         Info();
  200.         b->Info();
  201.     }
  202. #endif
  203.  
  204.     if (min_time<-EPS)    return NO_HIT;
  205.     else                        return min_time;
  206. }
  207.  
  208. void XWall::CollideWithBall( Ball *b )
  209. {
  210.     g->HitWall(b);
  211.     b->SetV(Vec2( - b->VX(), b->VY() ));
  212. }
  213.  
  214. //
  215. // -------------------------------------------------------------------------
  216. //   class YWall:  Wand ohne Begrenzung
  217. // -------------------------------------------------------------------------
  218. //
  219.  
  220. YWall::~YWall()    { }
  221.  
  222. Real YWall::HitFromBall( Ball *b )
  223. {
  224.     if (b->IsIdle())        return MAX_TIME;
  225.  
  226. Real    min_time;                    // ausgerechnete Zeit
  227. Real    sy=p1.Y()-b->PY();        // zurⁿckzulegende Strecke (ohne Radius)
  228.  
  229.     if (( sy > 0.0 ) && ( b->VY() > 0.0 )) {
  230.         sy -= b->R();                // Kugelradius berⁿcksichtigen
  231.     }
  232.     else if ( sy < 0.0 ) {
  233.         if ( b->VY() >= 0.0 )        return NO_HIT;
  234.         sy += b->R();                // Kugelradius berⁿcksichtigen
  235.     }
  236.     else if (b->VY()==0.0)            return NO_HIT;
  237.  
  238.     min_time = sy / b->VY();
  239.  
  240. #ifdef DEBUG
  241.     if (debug&YWallHit) {
  242.         printf( "YWall-Hit in %g secs\n", (double)min_time );
  243.         Info();
  244.         b->Info();
  245.     }
  246. #endif
  247.  
  248.     if (min_time<-EPS)    return NO_HIT;
  249.     else                        return min_time;
  250. }
  251.  
  252. void YWall::CollideWithBall( Ball *b )
  253. {
  254.     g->HitWall(b);
  255.     b->SetV(Vec2( b->VX(), - b->VY() ));
  256. }
  257.